package com.shi.yibanjia.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shi.yibanjia.annotation.Auth;
import com.shi.yibanjia.annotation.MyLog;
import com.shi.yibanjia.common.Result;
import com.shi.yibanjia.entity.dto.OrderPageQueryDto;
import com.shi.yibanjia.entity.po.Order;
import com.shi.yibanjia.enums.AuthCodeEnum;
import com.shi.yibanjia.enums.LogType;
import com.shi.yibanjia.service.OrderService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.List.of;

@RestController
@RequestMapping("/admin/order")
public class OrderController {

    @Resource
    private OrderService orderService;

    @GetMapping("/{page}/{size}")
    @Auth(hasPerm = AuthCodeEnum.BIZ_ORDER_DQL)
    @Cacheable(value = "yibanjia:order", key = "'page:'+#page+':size:'+#size+':queryParam:'+#orderPageQueryDto")
    public Result page(@PathVariable("page") Integer page,
                       @PathVariable("size") Integer size,
                       OrderPageQueryDto orderPageQueryDto) {
        String key = orderPageQueryDto.getKey();
        Page<Order> orderPage = orderService.page(new Page<>(page, size), new LambdaQueryWrapper<Order>()
                .like(StrUtil.isNotBlank(key), Order::getId, key)
                .orderByDesc(Order::getCreateTime));
        return Result.ok(orderPage);
    }

    @Auth(hasPerm = AuthCodeEnum.BIZ_ORDER_DQL)
    @GetMapping("/count")
    @Cacheable(value = "yibanjia:order", key = "'count'")
    public Result getCount() {
        long finished = orderService.count(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderStatus, 3, 4));
        long unFinished = orderService.count(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderStatus, 1, 2));
        return Result.ok(Map.of("count", finished + unFinished, "finished", finished, "unFinished", unFinished));
    }

    @MyLog(type = LogType.DELETE)
    @DeleteMapping
    @Auth(hasPerm = AuthCodeEnum.BIZ_ORDER_DML)
    @CacheEvict(value = "yibanjia:order", allEntries = true)
    public Result batchRemove(@RequestBody List<Long> ids) {
        orderService.removeBatchByIds(ids, 10, false);
        return Result.ok();
    }

    @MyLog(type = LogType.UPDATE)
    @PutMapping
    @Auth(hasPerm = AuthCodeEnum.BIZ_ORDER_DQL)
    @CacheEvict(value = "yibanjia:order", allEntries = true)
    public Result updateOrderStatus(@RequestBody Order order) {
        orderService.updateById(order);
        return Result.ok();
    }

    /**
     * 批量导出
     *
     * @param ids
     * @return
     */
    @MyLog
    @PostMapping("/export")
    @Auth(hasPerm = AuthCodeEnum.BIZ_ORDER_EXPORT)
    public void exportExcel(@RequestBody List<Long> ids, HttpServletResponse response) {
        List<Order> orderList = orderService.listByIds(ids);
        try {
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            EasyExcel.write(response.getOutputStream(), Order.class)
                    .autoCloseStream(true).build()
                    .write(() -> orderList, new WriteSheet()).finish();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @GetMapping("/currentMonth/money")
    public Result getMoneyCurrentMonth(@RequestParam("month") Integer month,
                                       @RequestParam("year") Integer year) {
        List<Order> orderList = orderService.list(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderStatus, 3, 4));
        double sum = orderList.stream().filter(item -> item.getUpdateTime().getYear() == year && item.getUpdateTime().getMonthValue() == month)
                .mapToDouble(item -> item.getCarryPrice().add(item.getTransportPrice()).doubleValue())
                .sum();
        return Result.ok(sum);
    }


    @GetMapping("/tenMonth/month")
    public Result getMoneyLatest10Month(@RequestParam("month") Integer month,
                                        @RequestParam("year") Integer year) {
        LocalDate localDate = LocalDate.of(year, month, 1);
        List<LocalDate> localDateList = new ArrayList<>(of(localDate,
                localDate.minusMonths(1),
                localDate.minusMonths(2),
                localDate.minusMonths(3),
                localDate.minusMonths(4),
                localDate.minusMonths(5),
                localDate.minusMonths(6),
                localDate.minusMonths(7),
                localDate.minusMonths(8),
                localDate.minusMonths(9)));
        Collections.reverse(localDateList);
        List<Order> orderList = orderService.list(new LambdaQueryWrapper<Order>()
                .in(Order::getOrderStatus, 3, 4));
        // 获取流水集合
        List<BigDecimal> moneyList = new ArrayList<>();
        for (LocalDate itemDate : localDateList) {
            double sum = orderList.stream().filter(item -> item.getUpdateTime().getYear() == itemDate.getYear() && item.getUpdateTime().getMonthValue() == itemDate.getMonthValue())
                    .mapToDouble(item -> item.getCarryPrice().add(item.getTransportPrice()).doubleValue())
                    .sum();
            moneyList.add(BigDecimal.valueOf(sum));
        }
        // 获取月份集合
        List<Integer> monthList = localDateList.stream().map(item -> item.getMonthValue()).collect(Collectors.toList());
        return Result.ok(Map.of("monthList", monthList, "moneyList", moneyList));
    }
}
